home *** CD-ROM | disk | FTP | other *** search
- /*
-
- 描画アルゴリズム
-
- void do_line_cont(int x1,int y1,int x2,int y2,void func(int x,int y)!)
- void do_line(int x1,int y1,int x2,int y2,void func(int x,int y)!)
-
- do_paint
- void do_blot(int x, int y, int branch, int depth,
- void pset(int x,int y,int gray)!)
- void do_polygon(POINT* points, int nPoint, void hline(int x1,int x2,int y)!)
-
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <winb.h>
- #include <te.h>
- #include <fntb.h>
- #include <gui.h>
- #include <egb.h>
- #include <wgb.h>
- #include <msdos.cf>
- #include "art.h"
- #include "guisub.h"
- #include "wgbmac.H"
-
- #include "subgrp.h"
- #include "imath.h"
-
- #define swap(a,b) { int t; t=(a); (a)=(b); (b)=t; }
-
-
- /*--------------------------------------------------------*/
- /* 描画アルゴリズム */
- /*--------------------------------------------------------*/
-
- void do_line_cont(int x1,int y1,int x2,int y2,void func(int x,int y)!)
- {
- int xr,yr,r,x,y;
- xr=abs(x2-x1),yr=abs(y2-y1);
- if (xr==0 && yr==0)
- ;
- else if (xr > yr)
- {
- r=(yr<<16)/xr; if(y1>y2) r=-r;
- if (x1 < x2)
- for (x=x1+1,y=(y1<<16)+0x8000+r; x<=x2; x++,y+=r)
- func(x,(y>>16));
- else
- for (x=x1-1,y=(y1<<16)+0x8000+r; x>=x2; x--,y+=r)
- func(x,(y>>16));
- }
- else
- {
- r=(xr<<16)/yr; if(x1>x2) r=-r;
- if (y1 < y2)
- for (y=y1+1,x=(x1<<16)+0x8000+r; y<=y2; y++,x+=r)
- func((x>>16),y);
- else
- for (y=y1-1,x=(x1<<16)+0x8000+r; y>=y2; y--,x+=r)
- func((x>>16),y);
- }
- }
-
- void do_line(int x1,int y1,int x2,int y2,void func(int x,int y)!)
- {
- func(x1,y1); // 最初の点
- do_line_cont(x1,y1,x2,y2,func);
- }
-
- void do_boxline(int x1,int y1,int x2,int y2,void func(int x,int y)!)
- {
- int i;
- if (x2<x1) swap(x1,x2);
- if (y2<y1) swap(y1,y2);
- for(i=x1;i<=x2;i++) func(i,y1);
- if(y1<y2)
- for(i=x1;i<=x2;i++) func(i,y2);
- for(i=y1+1;i<y2;i++) func(x1,i);
- if(x1<x2)
- for(i=y1+1;i<y2;i++) func(x2,i);
- }
-
- void do_boxfill(int x1,int y1,int x2,int y2,void func(int x1,int x2,int y)!)
- {
- int i;
- if (x2<x1) swap(x1,x2);
- if (y2<y1) swap(y1,y2);
- for(i=y1;i<=y2;i++) func(x1,x2,i);
- }
-
- void do_ellipse(int x,int y,int rx,int ry,void func(int x,int y)!)
- {
- #if 0
- #define ELLIPSE(RX,RY,X0,Y0,X1,Y1) \
- { \
- int x0=RX,s=x0; \
- int y0=0; \
- int px0=-1,py0=-1,px1=-1,py1=-1; \
- while(x0>=y0) \
- { \
- int x1=x0*RY/RX; \
- int y1=y0*RY/RX; \
- if(px0!=X0||py1!=Y1) \
- { \
- func(x+X0,y+Y1);if(X0!=0)func(x-X0,y+Y1); \
- if (Y1!=0) \
- { func(x+X0,y-Y1);if(X0!=0)func(x-X0,y-Y1); } \
- } \
- if (py0!=Y0||px1!=X1) \
- { \
- func(x+Y0,y+X1);if(Y0!=0)func(x-Y0,y+X1); \
- if (X1!=0) \
- { func(x+Y0,y-X1);if(Y0!=0)func(x-Y0,y-X1); } \
- } \
- s-=2*y0+1; if(s<0)s+=2*(x0-1),x0--; \
- y0++; \
- px0=X0,py0=Y0,px1=X1,py1=Y1; \
- } \
- }
- #
- if (rx==0 && ry==0)
- func(x,y);
- else if (rx>ry)
- ELLIPSE(rx,ry,x0,y0,x1,y1)
- else
- ELLIPSE(ry,rx,x1,y1,x0,y0)
- #undef ELLIPSE
- #endif
- if (rx==0 && ry==0)
- { func(x,y); return; }
- int px,py,prey;
- int a2,b2;
- int c1,c2;
- int e;
- a2=rx*rx,b2=ry*ry;
- px=0,py=ry;
- c1=4*b2,c2=8*a2;
- e=a2*(1-4*ry);
- while(b2*px<=a2*py)
- {
- func(x+px,y+py); if(px!=0)func(x-px,y+py);
- func(x+px,y-py); if(px!=0)func(x-px,y-py);
- prey=py;
- e+=c1*(2*px+1),px++; if(e>0) e-=c2*py,py--;
- }
- px=rx,py=0;
- c1=4*a2,c2=8*b2;
- e=b2*(1-4*rx);
- while(a2*py<=b2*px && py<prey)
- {
- func(x+px,y+py); if(px!=0)func(x-px,y+py);
- if(py!=0) { func(x+px,y-py); if(px!=0)func(x-px,y-py); }
- e+=c1*(2*py+1),py++; if(e>0) e-=c2*px,px--;
- }
- }
-
- void do_ellipsefill(int x,int y,int rx,int ry,void func(int x1,int x2,int y)!)
- {
- #if 0
- #define ELLIPSE(RX,RY,X0,Y0,X1,Y1) \
- { \
- int x0=RX,s=x0; \
- int y0=0; \
- int py0,py1; \
- py0=py1=INT_MIN; \
- while(x0>=y0) \
- { \
- int x1=x0*RY/RX; \
- int y1=y0*RY/RX; \
- if (y+Y1 != py0) \
- { \
- py0=y+Y1; \
- func(x-X0,x+X0,py0); \
- func(x-X0,x+X0,y-Y1); \
- } \
- if (y+X1 != py1) \
- { \
- py1=y+X1; \
- func(x-Y0,x+Y0,py1); \
- func(x-Y0,x+Y0,y-X1); \
- } \
- s-=2*y0-1; if(s<0)s+=2*(x0-1),x0--; \
- y0++; \
- } \
- }
- #
- if (rx==0&&ry==0)
- func(x,x,y);
- else if (rx>ry)
- ELLIPSE(rx,ry,x0,y0,x1,y1)
- else
- ELLIPSE(ry,rx,x1,y1,x0,y0)
- #undef ELLIPSE
- #endif
- if (rx==0 && ry==0)
- { func(x,x,y); return; }
- int px,py,prey;
- int a2,b2;
- int c1,c2;
- int e;
- a2=rx*rx,b2=ry*ry;
- px=0,py=ry;
- c1=4*b2,c2=8*a2;
- e=a2*(1-4*ry);
- prey=-1;
- while(b2*px<=a2*py)
- {
- e+=c1*(2*px+1);
- if(e>0)
- {
- func(x-px,x+px,y+py); func(x-px,x+px,y-py);
- prey=py;
- e-=c2*py,py--;
- }
- px++;
- }
- px=rx,py=0;
- c1=4*a2,c2=8*b2;
- e=b2*(1-4*rx);
- while(a2*py<=b2*px && py<prey)
- {
- func(x-px,x+px,y+py);
- if(py!=0) func(x-px,x+px,y-py);
- e+=c1*(2*py+1),py++; if(e>0) e-=c2*px,px--;
- }
- }
-
- /*--------------------------------------------------------*/
- /* ペイントルーチン */
- /*--------------------------------------------------------*/
-
- typedef struct {
- short int x,y;
- short int px1,px2,py;
- BOOL mark;
- } STACK;
-
- void do_paint(int x,int y, int picwid, int picht,
- void hline(int x1,int x2,int y)!,
- BOOL shouldPaint(int x,int y)!, // point(x,y) == border
- int srchleft(int x,int y)!,
- int srchright(int x,int y)!)
- {
- #define STACKSIZE 600
- // ラスタリージョンの追加を行う関数
- STACK *check(int px1,int px2,int py,int sx1,int sx2,int sy,
- int y, STACK *stack,int stacksize, STACK *sp)
- // 新しい sp を返す
- {
- int x;
- BOOL in_border;
- if (y<0 || picht<=y)
- return sp;
- in_border = TRUE;
- for (x=sx1; x<=sx2; x++) {
- if (in_border) {
- if (shouldPaint(x,y)) {
- if (!(y==py&&px1<=x&&x<=px2) && sp+1 < stack+stacksize) {
- sp++;
- sp->x = x;
- sp->y = y;
- sp->px1 = sx1;
- sp->px2 = sx2;
- sp->py = sy;
- sp->mark = TRUE;
- }
- in_border = FALSE;
- }
- } else {
- if (!shouldPaint(x,y))
- in_border = TRUE;
- }
- }
- return sp;
- }
- // ラスタリージョンの削除を行う関数
- void delete(int sx1,int sx2,int sy,STACK *oldsp, STACK *stack, STACK *sp)
- {
- STACK *p,*q;
- for (p=stack; p<=oldsp; p++) {
- if (p->y == sy && sx1 <= p->x && p->x <= sx2) {
- p->mark = FALSE;
- for (q = oldsp+1; q<=sp; q++) {
- if (q->y == p->py && p->px1 <= q->x && q->x <= p->px2)
- q->mark = FALSE;
- }
- }
- }
- }
- STACK stack[STACKSIZE];
- STACK *sp;
- STACK *oldsp;
- int sx,sx1,sx2,sy;
- int px1,px2,py;
-
- sp = stack;
- sp->x = x;
- sp->y = y;
- sp->px1 = 0;
- sp->px2 = 0;
- sp->py = 0;
- sp->mark = TRUE;
- while (sp >= stack) {
- if (sp->mark) {
- sx = sp->x;
- sy = sp->y;
- px1 = sp->px1;
- px2 = sp->px2;
- py = sp->py;
- sx1 = srchleft(sx,sy);
- // for (sx1=sx,ip=(short*)EIMadrs(sx1,sy);
- // sx1 > 0 && *(ip-1) == border;
- // sx1--,ip--)
- // ;
- sx2 = srchright(sx,sy);
- // for (sx2=sx,ip=(short*)EIMadrs(sx2,sy);
- // sx2 < EIMgetxsize()-1 && *(ip+1) == border;
- // sx2++,ip++)
- // ;
- hline(sx1,sx2,sy);
- oldsp = --sp;
- sp=check(px1,px2,py,sx1,sx2,sy,sy+1, stack,STACKSIZE, sp);
- sp=check(px1,px2,py,sx1,sx2,sy,sy-1, stack,STACKSIZE, sp);
- delete(sx1,sx2,sy,oldsp, stack,sp);
- } else
- sp--;
- }
- }
-
- void do_blot(int x, int y, int branch, int depth,
- void pset(int x,int y,int gray)!)
- // branch : 枝分かれする数
- // depth : 何回再帰するか
- // gray : 0..50 程度
- {
- if (depth <= 0)
- return;
- deci branchsub = IntToDeci(branch)/_max(1,depth/3);
- void blot_plot_sub(int x,int y,deci branch,int depth,
- deci grad, deci gradsub)
- {
- if (depth <= 0 || grad <= 0)
- return;
- pset(x,y,DeciToInt(grad));
- int b;
- for (b=0; b<_max(1,DeciToInt(branch)); b++)
- {
- int nx,ny;
- nx = x + rand() % 3 - 1;
- ny = y + rand() % 3 - 1;
- blot_plot_sub(nx,ny,branch-branchsub,depth-1,grad-gradsub,gradsub);
- }
- }
- blot_plot_sub(x,y,IntToDeci(branch),depth,
- IntToDeci(50),IntToDeci(50)/depth);
- }
-
- #define MAXY 2000
-
- static short **xbuf = NULL; // ポリゴン指定用ワーク
- #define XBUFMAX 10
- #define RIGHTMAX 0x7fff
-
- void do_polygon(POINT* points, int nPoint, void hline(int x1,int x2,int y)!)
- {
- if (xbuf == NULL)
- {
- if ((xbuf = TL_calloc(1,sizeof(short*)*MAXY)) == NULL)
- return;
- short* buf = TL_calloc(sizeof(short),XBUFMAX*MAXY);
- if (buf == NULL)
- { TL_free(xbuf); xbuf = NULL; return; }
- for (int i=0; i<MAXY; i++)
- xbuf[i] = buf + XBUFMAX*i;
- }
- int i;
- for (i=0; i<MAXY; i++)
- xbuf[i][0] = RIGHTMAX;
- int getsign(int n)
- { return (n<0 ? -1 : n>0 ? 1 : 0); }
- int pnum = nPoint; // 頂点の数
- int f1,f2;
- // 始点での頂点の例外処理のために、前の辺の符号をきめる
- f1=0;
- for (i=1; i<pnum; i++) {
- f2=getsign(points[i].y-points[i-1].y);
- if (f2!=0)
- f1=f2;
- }
- f2=getsign(points[0].y-points[pnum-1].y);
- if (f2!=0)
- f1=f2;
- // x 座標リストの作成
- void makebuf(int x1,int y1,int x2,int y2)
- {
- void sort_x() // (x1,y1) をバッファに登録する
- {
- if (y1 < 0 || MAXY <= y1)
- return;
- for (int i=0; i<XBUFMAX; i++)
- {
- if (xbuf[y1][i] > x1)
- {
- if (i==XBUFMAX-1)
- {
- xbuf[y1][i] = x1;
- return;
- }
- for (int j=XBUFMAX-1; j>i; j--)
- xbuf[y1][j] = xbuf[y1][j-1];
- xbuf[y1][i] = x1;
- break;
- }
- }
- }
- int f2;
- f2 = getsign(y2-y1);
- if (f2==0)
- return;
- if (f1*f2==-1)
- sort_x();
- int dx,dy,ux,uy;
- dx = abs(x2-x1);
- dy = abs(y2-y1);
- ux = getsign(x2-x1);
- uy = getsign(y2-y1);
- if (dx >= dy) {
- int r = dx/2;
- for (;;) {
- if (x1==x2) {
- f1=f2;
- break;
- }
- x1 += ux, r += dy;
- if (r >= dx) {
- r -= dx, y1 += uy;
- sort_x();
- }
- }
- } else {
- int r = dy/2;
- for (;;) {
- if (y1==y2) {
- f1=f2;
- break;
- }
- y1 += uy, r += dx;
- if (r >= dy)
- r -= dy, x1 += ux;
- sort_x();
- }
- }
- }
- for (i=0; i<pnum-1; i++)
- makebuf(points[i].x,points[i].y,points[i+1].x,points[i+1].y);
- makebuf(points[pnum-1].x,points[pnum-1].y,points[0].x,points[0].y);
- for (i=0; i<MAXY; i++) {
- for (int j=0; j<XBUFMAX; j+=2) {
- if (_max(xbuf[i][j],xbuf[i][j+1]) < RIGHTMAX)
- hline(xbuf[i][j],xbuf[i][j+1],i);
- else
- break;
- }
- }
- }
-
-